﻿using MiniJob.Worker.Jobs;
using System.Collections.ObjectModel;

namespace MiniJob.Worker.Runtime;

public sealed class JobRegistrationCollection : KeyedCollection<JobTypeInformation, JobRegistration>
{
    protected override JobTypeInformation GetKeyForItem(JobRegistration item)
    {
        return item.Type;
    }

    /// <summary>
    /// Registers an job type in the collection.
    /// </summary>
    /// <typeparam name="TJob">Type of job.</typeparam>
    /// <param name="configure">An optional delegate used to configure the job registration.</param>
    public void RegisterJob<TJob>(Action<JobRegistration>? configure = null)
        where TJob : Job
    {
        RegisterJob<TJob>(jobTypeName: null, configure);
    }

    /// <summary>
    /// Registers an job type in the collection.
    /// </summary>
    /// <typeparam name="TJob">Type of job.</typeparam>
    /// <param name="typeOptions">An optional <see cref="JobRuntimeOptions"/> that defines values for this type alone.</param>
    /// <param name="configure">An optional delegate used to configure the job registration.</param>
    public void RegisterJob<TJob>(MiniJobRuntimeOptions typeOptions, Action<JobRegistration>? configure = null)
        where TJob : Job
    {
        RegisterJob<TJob>(null, typeOptions, configure);
    }

    /// <summary>
    /// Registers an job type in the collection.
    /// </summary>
    /// <typeparam name="TJob">Type of job.</typeparam>
    /// <param name="jobTypeName">The name of the job type represented by the job.</param>
    /// <param name="configure">An optional delegate used to configure the job registration.</param>
    /// <remarks>The value of <paramref name="jobTypeName"/> will have precedence over the default job type name derived from the job implementation type or any type name set via <see cref="JobAttribute"/>.</remarks>
    public void RegisterJob<TJob>(string? jobTypeName, Action<JobRegistration>? configure = null)
        where TJob : Job
    {
        RegisterJob<TJob>(jobTypeName, null, configure);
    }

    /// <summary>
    /// Registers an job type in the collection.
    /// </summary>
    /// <typeparam name="TJob">Type of job.</typeparam>
    /// <param name="jobTypeName">The name of the job type represented by the job.</param>
    /// <param name="typeOptions">An optional <see cref="JobRuntimeOptions"/> that defines values for this type alone.</param>
    /// <param name="configure">An optional delegate used to configure the job registration.</param>
    /// <remarks>The value of <paramref name="jobTypeName"/> will have precedence over the default job type name derived from the job implementation type or any type name set via <see cref="JobAttribute"/>.</remarks>
    public void RegisterJob<TJob>(string? jobTypeName, MiniJobRuntimeOptions? typeOptions, Action<JobRegistration>? configure = null)
        where TJob : Job
    {
        var jobTypeInfo = JobTypeInformation.Get(typeof(TJob), jobTypeName);
        var registration = new JobRegistration(jobTypeInfo, typeOptions);
        configure?.Invoke(registration);
        this.Add(registration);
    }
}
